package com.zxs.springbootexp3.service;

import com.zxs.springbootexp3.model.RegionData;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CoronaVirusDataService implements InitializingBean {

    final String CONFIRMED_DATA_URL = "https://gitee.com/dgut-sai/COVID-19/raw/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv";

    final String DEADTHS_DATA_URL = "https://gitee.com/dgut-sai/COVID-19/raw/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv";

    final String RECOVERED_DATA_URL = "https://gitee.com/dgut-sai/COVID-19/raw/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv";

    final String User_Agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36";

    final String STAT = "Province/State";

    final String COUNTRY = "Country/Region";

    private final List<RegionData> allRegionData = new ArrayList<RegionData>();

    private final List<Integer> total = new ArrayList<Integer>();

    public List<RegionData> getAllRegionData() {return allRegionData;}

    public List<Integer> getTotal() {return total;}

    public Resource getResource(String url) {

        RequestEntity<Void> requestEntity = RequestEntity
                .get(URI.create(url))
                .headers(httpHeaders -> httpHeaders.add("User-Agent", User_Agent))
                .build();
        ResponseEntity<Resource> exchange =
                new RestTemplate().exchange(requestEntity, Resource.class);
        Resource body = exchange.getBody();
        return body;
    }

    //查询
    public List<RegionData> queryByKeyword(List<RegionData> data, String keyword) {
        return data.parallelStream().filter(d->d.getState().toLowerCase().contains(keyword.toLowerCase())||d.getCountry().toLowerCase().contains(keyword.toLowerCase())).collect(Collectors.toUnmodifiableList());
    }

    //两个关键词搜索
    public List<CSVRecord> queryByKeyword(List<CSVRecord> data, String stat, String country) {
        return data.parallelStream().filter(d->d.get(STAT).contains(stat)&&d.get(COUNTRY).contains(country)).collect(Collectors.toUnmodifiableList());
    }

    public List<CSVRecord> getRecords(String url) throws IOException {

        //获取csv文件的输入流
        Resource body = getResource(url);
        InputStream inputStream = body.getInputStream();

        //获取record
        InputStreamReader isr = new InputStreamReader(inputStream);
        List<CSVRecord> records = new CSVParser(isr, CSVFormat.DEFAULT.withFirstRecordAsHeader()).getRecords();

        return records;
    }

    @Scheduled(cron = "0 0 1 * * *")
    public void CreateList() throws IOException {

        //生成三种数据的records
        List<CSVRecord> confirmed_records = getRecords(CONFIRMED_DATA_URL);
        List<CSVRecord> deaths_records = getRecords(DEADTHS_DATA_URL);
        List<CSVRecord> recovered_records = getRecords(RECOVERED_DATA_URL);

        //获取数据,存进allRegionData
        for(int i=0;i<confirmed_records.size();i++) {

            RegionData data = new RegionData();
            CSVRecord cr = confirmed_records.get(i);
            CSVRecord dr = deaths_records.get(i);

            //set confirmed data
            data.setState(cr.get(STAT));
            data.setCountry(cr.get(COUNTRY));
            data.setLatestTotalCases(Integer.parseInt(cr.get(cr.size() - 1)));
            data.setDiffFromPrevDay(Integer.parseInt(cr.get(cr.size() - 1)) - Integer.parseInt(cr.get(cr.size() - 2)));
            //set deaths data
            data.setDeathsTotalCases(Integer.parseInt(dr.get(dr.size() - 1)));

            //set recovered data
            //由于recovered数据量与其他两个数据不一样，需要单独处理
            //find recovered data
            List<CSVRecord> query = queryByKeyword(recovered_records, data.getState(), data.getCountry());

            if(query.isEmpty()) {
                data.setRecoveredTotalCases(0);
            }else{
                CSVRecord q = query.get(0);
                data.setRecoveredTotalCases(Integer.parseInt(q.get(q.size()-1)));
            }

            allRegionData.add(data);
        }

        List<RegionData> ar = allRegionData.stream().sorted(Comparator.comparing(RegionData::getLatestTotalCases).reversed().thenComparing(RegionData::getDeathsTotalCases)).collect(Collectors.toUnmodifiableList());
        for(int i=0;i<allRegionData.size();i++) {
            allRegionData.set(i, ar.get(i));
        }
        //计算总和
        int confirmedTotal = allRegionData.stream().mapToInt(RegionData::getLatestTotalCases).sum();
        int deathsTotal = allRegionData.stream().mapToInt(RegionData::getDeathsTotalCases).sum();
        int recoveredTotal = allRegionData.stream().mapToInt(RegionData::getRecoveredTotalCases).sum();
        total.add(confirmedTotal);
        total.add(deathsTotal);
        total.add(recoveredTotal);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        CreateList();
    }
}
